package MelbourneMap;

import java.awt.*;
import java.awt.geom.*;
import java.util.*;

import javax.swing.JPanel;

/**
 * DrawPanel is the panel to which all regions of the map are drawn.
 * It contains a list of {@link Region} objects that can be set using
 * setShapes. These regions are then drawn to the panel when it is 
 * painted. The region shapes will be transformed using an affine 
 * transform object that can be set using setAffine.
 * 
 * @author David Zappia, 7183216
 * @author Heong Jin Yu, 7019777
 * 
 */
class DrawPanel extends JPanel
{
	static final long serialVersionUID = 2L;
	private Map<String, Region>[] regionList;
	private ArrayList<Vehicle> vehicleList;
	private AffineTransform AT;
	
	/** 
	 * Class constructor
	 */
	public DrawPanel()
	{
		regionList = new HashMap[5];
		vehicleList = new ArrayList<Vehicle>();
		AT = new AffineTransform();
		setLayout(null);
	}
	
	/**
	 * Draws each specified Region objects by reading the details
	 * within and applying the specified affine transformation.
	 * Must be called by using repaint().
	 */
	public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		setBackground(new Color(165, 191, 221));
		Graphics2D g2 = (Graphics2D) g;
		int type;
		
		AffineTransform saveXform = new AffineTransform(g2.getTransform());
		Stroke strk = g2.getStroke();
		g2.transform(AT);
		
		for (int i = 0; i < regionList.length; i++)
		{
			if (regionList[i] != null)
			{
				Map<String, Region> map = regionList[i];
				Iterator it = map.keySet().iterator();
				
				while (it.hasNext()) 
		        {  
		           String key = it.next().toString();
		           
		           type = map.get(key).getType();
		           
		           switch (type)
		           {
		           case -2:
		        	   g2.setPaint(Color.blue);
		        	   g2.setStroke(strk);
		        	   break;
		           case 0:
		        	   g2.setPaint(Color.green);
		        	   g2.setStroke(new BasicStroke(16));
		        	   break;
		           case 1:
		        	   g2.setPaint(Color.black);
		        	   g2.setStroke(new BasicStroke(12));
		        	   break;
		           case 2:
		        	   g2.setPaint(Color.red);
		        	   g2.setStroke(new BasicStroke(8));
		        	   break;
		           case 3:
		        	   g2.setPaint(Color.orange);
		        	   g2.setStroke(new BasicStroke(6));
		        	   break;
		           case 4:
		           case 5:
		        	   g2.setPaint(Color.getHSBColor(14, 99, 128));
		        	   g2.setStroke(new BasicStroke(4));
		        	   break;
		           default:
		        	   g2.setPaint(Color.black);
		        	   g2.setStroke(strk);
		        	   break;
		           }	
		           //System.out.println("Drawing: " + key);
		           
		           if (i == 0)
		           {
		        	   g2.setPaint(new Color(244, 243, 240));//Color(156, 224, 167));
		        	   g2.fill(map.get(key).getShape());
		        	   g2.setPaint(Color.black);
		           }
		           //Suburb
		           else if (i == 1)
		           {
		        	   g2.setPaint(Color.black);
		        	   g2.setStroke(new BasicStroke(40));
		        	   g2.draw(map.get(key).getShape());
		        	   if(map.get(key).getColor()!=null && map.get(key).selected)
		        		   g2.setPaint(map.get(key).getColor());
		        	   else
		        		   g2.setPaint(Color.lightGray);
		        	   g2.fill(map.get(key).getShape());
		        	   g2.setPaint(Color.black);
		           }
		           else if (i == 2)
		           {
		        	   
		        	   if(map.get(key).selected)
		        	   {
		        		   g2.setStroke(new BasicStroke(40));
		        		   g2.draw(map.get(key).getShape());
			        	   for(Node n : map.get(key).getData())
			        	   {
			        		   g2.setPaint(Color.black);
			        		   g2.setStroke(new BasicStroke(2));
			        		   g2.draw(n.getShape());
			        	   }
		        	   }
		        	   else
		        		   g2.draw(map.get(key).getShape());
		           }
		           else if (i == 3)
		           {   
		        	   if(map.get(key).selected)
		        	   {
		        		   g2.setPaint(Color.pink);
		        		   g2.setStroke(new BasicStroke(40));
		        		   g2.draw(map.get(key).getShape());
			        	   for(Node n : map.get(key).getData())
			        	   {
			        		   g2.setPaint(Color.black);
			        		   g2.setStroke(new BasicStroke(2));
			        		   g2.draw(n.getShape());
			        	   }
		        	   }
		        	   else
		        		   g2.draw(map.get(key).getShape());
		           }
		           else
		           {
		        	   //g2.setPaint(map.get(key).getColor());
		        	   g2.draw(map.get(key).getShape());
		           }
		        }
			}
		}
		
		drawVehicles(g2);
		
		g2.setPaint(Color.black);
 	    g2.setStroke(strk);
		g2.setTransform(saveXform);
	}
	
	private void drawVehicles(Graphics2D g2)
	{
		g2.setPaint(Color.blue);
		for (Vehicle v : vehicleList)
		{
			g2.setStroke(new BasicStroke(2));
		   	g2.draw(v.getShape());
		   	g2.fill(v.getShape());
		}
	}
	
	/**
	 * Sets the list of Region objects to be drawn to the panel. The regions
	 * will then be drawn when the panel is painted.
	 * 
	 * @param regions	the list of regions to be drawn
	 * @see 			Region
	 */
	public void setShapes(Map<String, Region>[] regions)
	{
		regionList = regions;
	}
	
	public synchronized void setVehicles(ArrayList<Vehicle> vehicles)
	{
		vehicleList = vehicles;
	}
	
	/**
	 * Sets the affine transformation to be used when the panel is painted.
	 * <p>
	 * The affine object reshapes each region in a uniform way so that
	 * they all fit together neatly.
	 * 
	 * @param affine	the affine transformation object to be used
	 */
	public void setAffine(AffineTransform affine)
	{
		AT = affine;
	}
	
	public void addVehicle(Vehicle v)
	{
		vehicleList.add(v);
	}
	
	public ArrayList<Vehicle> getVehicle()
	{
		return vehicleList;
	}
}
